﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using XMLGener.Utils;

namespace XMLGener.Data
{
    /// <summary>
    /// This class is used for managing data types.
    /// </summary>
    public class XMLGenerDataTypes:XMLGenerNode
    {
        private static XDataTypeCollection baseTypesList = null;


        /// <summary>
        /// Create data types collection from node
        /// </summary>
        /// <param name="xmlElem">Source xml elmement for setting data types</param>
        public XMLGenerDataTypes(XmlElement xmlElem)
            : base(null, xmlElem)
        {
            this.xtype = XNodeType.DATATYPES;
        }

        /// <summary>
        ///  Funcion initialize base data types.
        /// </summary>
        /// <param name="typesElement"></param>
        public static void loadBaseDataTypes(XmlElement typesElement)
        {
            XDataTypeCollection list = new XDataTypeCollection();
            XmlElement node = XMLUtils.getSubElement(typesElement, XMLGenerNode.XDATATYPE_STR);
            XDataType newType = null;
            while (node != null)
            {
                newType = new XDataType(node);
                newType.isBaseType = (XMLUtils.getAttribute(node,"isBase","0") == "1");
                list.Add(newType);
                node = XMLUtils.getNextElement(node, XMLGenerNode.XDATATYPE_STR);
            }
            baseTypesList = list;
            if (list.getItem("any") == null)
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml("<dataType name=\"any\">");
                XmlElement el = doc.DocumentElement;
                XDataType anyDataType = new XDataType(el);
                anyDataType.isBaseType = true;
                list.Add(anyDataType);
            }

            
            loadModules();
        }

        private static void loadModules()
        {
            foreach (XModuleDefinitionInstance mod in XModuleManager.modDefinitionList.Values)
            {
                XDataType type = baseTypesList.getItem(mod.restirction.dataType) as XDataType;
                if (type!=null)
                    type.addMatchingModule(mod);
            }
            Queue<XDataType> q = new Queue<XDataType>();
            q.Enqueue(baseTypesList.getItem("any") as XDataType);

            foreach (XDataType dataType in baseTypesList)
            {
                if (dataType==null)
                    continue;
                if (string.IsNullOrEmpty(dataType.parentTypeName))
                { 
                    q.Enqueue(dataType);
                }
            }

            XDataType tp = null;
            //List<XDataType> childs = new List<XDataType>();
            while (q.Count>0)
            {
                tp = q.Dequeue();
                //childs.Clear();
                foreach (XDataType childType in baseTypesList)
                {
                    if (childType.parentTypeName==tp.name)
                    {
                        //childs.Add(childType);
                        childType.loadModules();
                        if (childType.name!="any")
                            q.Enqueue(childType);
                    }
                }



            }


        }

        /// <summary>
        /// Return default data types.
        /// </summary>
        /// <returns></returns>
        public static XDataTypeCollection getDefaultTypes()
        {
            return baseTypesList;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="parent"></param>
        public XMLGenerDataTypes(XMLGenerNode parent)
            : base(XMLGenerNode.XDATATYPES_STR, parent)
        {
            this.xtype = XNodeType.DATATYPES;
        }

        /// <summary>
        /// 
        /// </summary>
        protected override void defaultInitialization()
        {
            base.defaultInitialization();
            this.nodeTypeStr = XMLGenerNode.XDATATYPES_STR;
        }
        
        //---------------------------
        // attributes from xml
        //---------------------------
        /// <summary>
        /// 
        /// </summary>
        public override String name
        {
            get { return "Data types"; }
            set { ; }
        }
       

       
    }
}
